package huanzhao.erp.service;

import cn.dev33.satoken.stp.StpUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import huanzhao.erp.domain.entity.GlobalSetting;
import huanzhao.erp.domain.entity.Operation;
import huanzhao.erp.domain.entity.Staff;
import huanzhao.erp.domain.enumerate.error.ValidationError;
import huanzhao.erp.domain.po.Result;
import huanzhao.erp.domain.types.OperationTarget;
import huanzhao.erp.domain.types.OperationType;
import huanzhao.erp.domain.types.PhoneAttr;
import huanzhao.erp.mapper.GlobalSettingMapper;
import huanzhao.erp.mapper.OperationMapper;
import huanzhao.erp.mapper.StaffMapper;
import huanzhao.erp.other.config.ProjectConfig;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;

/**
 * @author April
 * 2024/6/12 上午10:07
 * @version 1.0
 */
@Service
public class BasicService {
    private static final Logger log = LoggerFactory.getLogger(BasicService.class);
    final HttpSession session;
    // 全局的ObjectMapper
    private final ObjectMapper objectMapper;
    private final ProjectConfig projectConfig;
    private final GlobalSettingMapper globalSettingMapper;
    private final ConvertService convertService;
    private final StaffMapper staffMapper;
    private final OperationMapper operationMapper;


    public BasicService(HttpSession session, ObjectMapper objectMapper, ProjectConfig projectConfig, GlobalSettingMapper globalSettingMapper, ConvertService convertService, StaffMapper staffMapper, OperationMapper operationMapper) {
        this.session = session;
        this.objectMapper = objectMapper;
        this.projectConfig = projectConfig;
        this.globalSettingMapper = globalSettingMapper;
        this.convertService = convertService;
        this.staffMapper = staffMapper;
        this.operationMapper = operationMapper;
    }

    /**
     * 校验图片验证码
     *
     * @param captcha 图片验证码
     * @return Result<?>
     * 2024/1/7 21:46:15
     */
    public Result<?> checkCaptcha(String captcha) {
        if (projectConfig.getDevMode()) {
            return Result.ok("开发环境，跳过校验图片验证码");
        }
        // 校验图片验证码
        Object sessionAttribute = session.getAttribute("JCCODE");
        // 清空session中的验证码，以防重复调用接口
        session.removeAttribute("JCCODE");
        if (sessionAttribute == null) {
            return Result.error(ValidationError.VERIFICATION_CODE_NOT_EXIST);
        }
        String jccode = String.valueOf(sessionAttribute).toLowerCase();
        if (StringUtils.isBlank(captcha)) {
            return Result.error(ValidationError.VERIFICATION_CODE_BLANK, "请输入图片验证码");
        }
        if (!jccode.equals(captcha.toLowerCase())) {
            return Result.error(ValidationError.VERIFICATION_CODE_ERROR, "图片验证码校验失败");
        }
        return Result.ok("图片验证码校验成功");
    }

    /**
     * 获取当前登录员工
     *
     * @return Staff
     * 2024/1/6 14:01:25
     */
    public Staff getCurrentStaff() {
        return (Staff) StpUtil.getSession().get("staff");
    }

    /**
     * 获取当前登录员工id
     *
     * @return Long
     * 2024/1/9 17:20:19
     */
    public Long getCurrentStaffId() {
        return StpUtil.getLoginIdAsLong();
    }

    /**
     * 获取全局设置
     *
     * @return GlobalSetting
     * 2024/10/4 14:26:02
     */
    public GlobalSetting getGlobalSetting() {
        // todo: 需要添加缓存
        GlobalSetting globalSetting = globalSettingMapper.selectById(1);
        if (globalSetting == null) {
            return new GlobalSetting(0L, 0L, 0L, 0L, 0L, 0L, 0L);
        }
        return globalSetting;
    }

    /**
     * 将对象解析为json字符串
     *
     * @param obj 对象
     * @return String
     * 2024/6/21 下午10:27:46
     */
    public String parseObj2Json(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("解析对象为json字符串失败，对象信息为：{}", obj, e);
            return "";
        }
    }


    /**
     * 记录当前员工的操作日志
     *
     * @param type     操作类型
     * @param target   操作对象
     * @param detail   操作详情
     * @param relateId 关联id
     * @param attr     手机属性
     *                 2024/10/10 09:59:54
     */
    public void recordOps(@NonNull OperationTarget target, @NonNull OperationType type, Object detail, Long relateId, PhoneAttr attr) {
        // 将日志记入数据库
        recordOps(getCurrentStaffId(), target, type, detail, relateId, attr);
    }

    /**
     * 按员工id记录操作日志
     *
     * @param staffId  员工id
     * @param type     操作类型
     * @param target   操作对象
     * @param detail   操作详情
     * @param relateId 关联id
     * @param attr     手机属性
     *                 2024/10/10 19:34:33
     */
    public void recordOps(Long staffId, @NonNull OperationTarget target, @NonNull OperationType type, Object detail, Long relateId, PhoneAttr attr) {
        // 将日志记入数据库
        try {
            operationMapper.insert(new Operation(staffId, type, target, detail, relateId, attr));
        } catch (Exception e) {
            log.error("记录操作日志失败，操作类型：{}，操作对象：{}，操作详情：{}，关联id：{}，属性：{}", type, target, detail, relateId, attr, e);
        }
    }


    public void recordOps(@NonNull OperationTarget target, @NonNull OperationType type, Long relateId) {
        recordOps(target, type, null, relateId, null);
    }

    public void recordOps(@NonNull OperationTarget target, @NonNull OperationType type, Long relateId,Object detail) {
        recordOps(target, type, detail, relateId, null);
    }

    public void recordOps(Long staffId, @NonNull OperationTarget target, @NonNull OperationType type, Long relateId) {
        recordOps(staffId, target, type, null, relateId, null);
    }

    /**
     * 记录修改手机字段的操作日志
     *
     * @param phoneId 手机id
     * @param attr    手机属性
     * @param detail  操作详情，比如字段值的更改
     *                2024/10/10 10:02:35
     */
    public void recordUpdatePhoneAttrOps(Long phoneId, PhoneAttr attr, @NonNull Object detail) {
        recordOps(OperationTarget.PHONE, OperationType.UPDATE, detail, phoneId, attr);
    }
}
